-- SPDX-License-Identifier: GPL-3.0-or-later

local extension = Package:new("old2")
-- extension.extensionName = "vupslash"
extension.extensionName = "VslTest"
-- extension.game_modes_whitelist = { 'nos_heg_mode', 'new_heg_mode' }
-- dofile "packages/vupslash/game_rule.lua"

-- local VslUtil = require "packages/vupslash/util"
local VslUtil = require "packages/VslTest/util"

--------------------------------------------------
--测试技能：超级英姿
--------------------------------------------------

local super_yingzi = fk.CreateTriggerSkill{
	name = "superyingzi",
	anim_type = "drawcard",
	events = {fk.DrawNCards},
	on_use = function(self, event, target, player, data)
		data.n = data.n + 20
	end,
}

--------------------------------------------------
--测试技能：摸指定牌
--------------------------------------------------

local v_cheat = fk.CreateActiveSkill{
	name = "v_cheat",
	anim_type = "drawcard",
	can_use = function(self, player)
		return true
	end,
	on_use = function(self, room, effect)
		local from = room:getPlayerById(effect.from)
		local cardTypeName = room:askForChoice(from, { 'basic', 'trick', 'equip' }, "cheat")
		local cardType = Card.TypeBasic
		if cardTypeName == 'trick' then
			cardType = Card.TypeTrick
		elseif cardTypeName == 'equip' then
			cardType = Card.TypeEquip
		end

		local allCardIds = Fk:getAllCardIds()
		local allCardMapper = {}
		local allCardNames = {}
		for _, id in ipairs(allCardIds) do
			local card = Fk:getCardById(id)
			if card.type == cardType then
				if allCardMapper[card.name] == nil then
					table.insert(allCardNames, card.name)
				end

				allCardMapper[card.name] = allCardMapper[card.name] or {}
				table.insert(allCardMapper[card.name], id)
			end
		end

		if #allCardNames == 0 then
			return
		end

		local cardName = room:askForChoice(from, allCardNames, "cheat")
		local toGain = nil
		if #allCardMapper[cardName] > 0 then
			toGain = allCardMapper[cardName][math.random(1, #allCardMapper[cardName])]
		end

		from:addToPile(self.name, toGain, true, self.name)
		room:obtainCard(effect.from, toGain, true, fk.ReasonPrey)
	end
}
  
--------------------------------------------------
--测试技能：流失体力
--------------------------------------------------

local v_lose = fk.CreateActiveSkill{
	name = "v_lose",
	anim_type = "offensive",
	can_use = function(self, player)
		return true
	end,
	target_num = 1,
	-- card_num = 1,
	card_filter = function(self, to_select, selected, selected_targets)
		return false
		-- if #selected == 1 then return false end
		-- return Fk:currentRoom():getCardArea(to_select) ~= Player.Equip
	end,
	target_filter = function(self, to_select, selected)
		-- local target = Fk:currentRoom():getPlayerById(to_select)
		return #selected == 0
	end,
	on_use = function(self, room, effect)
		local player = room:getPlayerById(effect.from)
		local target = room:getPlayerById(effect.tos[1])
		room:loseHp(target, 1, self.name)
	end,
}

--------------------------------------------------
--作业
--------------------------------------------------

local v_zuoye = fk.CreateTriggerSkill{
  name = "v_zuoye",
  anim_type = "control",
  mute = true,
  events = {fk.EventPhaseStart},
  --触发条件：
  -- ...遍历到的角色持有该技能；
  -- 触发时机的角色处于准备阶段;
  -- 触发时机的角色判定区中存在牌。
  -- （待补充）技能没有被无效；遍历到的角色的技能可以对触发时机的角色产生影响。
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self) and
      player.phase == Player.Finish and
      player:getHandcardNum() < player.hp
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    local targets = {}
    local others = room:getOtherPlayers(player)
    local prompt = "#v_zuoye_ask"
    for _,p in ipairs(others) do
      --后续可以在这里补充以下判定：
      -- caneffect，目标可以弃置遍历到的角色的牌(candiscard)。
      if VslUtil.SkillCanTarget(p, player, self.name) then
        table.insert(targets, p.id)
      end
    end
    local ret = room:askForChoosePlayers(player, targets, 1, 1, prompt, self.name, true)
    --确认是否发动技能。
    if #ret > 0 then
      --后续可以在这里补充以下判定：
      -- 遍历到的角色本技能未被元初之类的无效，目标可以弃置遍历到的角色的牌。
      self.cost_data = ret[1]
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local tar = room:getPlayerById(self.cost_data)
    room:doAnimate("InvokeSkill", {
      name = self.name,
      player = player.id,
      skill_type = self.anim_type,
    })
    room:sendLog{
      type = "#v_skill_target",
      from = player.id,
      arg = self.name,
      to = { tar.id }
    }
    player:broadcastSkillInvoke(self.name)
    tar:drawCards(2, self.name)
    room:delay(500)
    if tar.dead then
      return false
    end
    local targets = {}
    local slash = Fk:cloneCard("slash")
    for _,p in ipairs(room:getOtherPlayers(tar)) do
      --后续可以在这里补充以下判定：
      -- caneffect，目标可以弃置遍历到的角色的牌(candiscard)。
      if VslUtil.canUseCardTo(room, tar, p, slash, true, true) then
        table.insert(targets, p.id)
      end
    end
    local vic = nil
    if #targets > 0 then
      vic = room:askForChoosePlayers(player, targets, 1, 1, "#v_zuoye_ask2::"..tar.id, self.name, false, false)[1]
    end
    if vic and room:getPlayerById(vic):isAlive() then
      room:doIndicate(tar.id, { vic })
      room:sendLog{
        type = "#v_zuoye_slash_victim_log",
        from = tar.id,
        to = {vic},
        arg = self.name,
      }
      local cid = {}
      for _, id in ipairs(tar:getCardIds(Player.Hand)) do
        if Fk:getCardById(id).trueName == "slash" then
          table.insertIfNeed(cid, id)
        end
      end
      --这牌怎么没用出来？
      local use = room:askForUseCard(tar, "slash", nil, "#v_zuoye_slash_use::"..vic, true, { must_targets = {vic} })
      if not use then
        tar:turnOver()
      else
        room:useCard(use)
      end
    else
      tar:turnOver()
    end
  end
}

--------------------------------------------------
--北柚香
--------------------------------------------------

local beiyouxiang_motaishouke = General(extension,"beiyouxiang_motaishouke", "psp", 4, 4, General.Female)
beiyouxiang_motaishouke:addSkill(v_zuoye)

--------------------------------------------------
--星耀
--------------------------------------------------

local v_xingyao = fk.CreateTriggerSkill{
  name = "v_xingyao",
  anim_type = "offensive",
  events = {fk.TargetSpecified},
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self) and
      data.card.trueName == "slash"
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local to = room:getPlayerById(data.to)
    data.fixedResponseTimes = data.fixedResponseTimes or {}
    local judge = {
      who = player,
      reason = self.name,
      pattern = ".|.|heart,diamond",
    }
    room:judge(judge)
    if judge.card.color == Card.Red then
      data.fixedResponseTimes["jink"] = 2
      data.additionalDamage = (data.additionalDamage or 0) + 1
    else
      room:addPlayerMark(to, "@@v_xingyao-turn", 1)
      room:addPlayerMark(to, MarkEnum.UncompulsoryInvalidity .. "-turn", 1)
      room:addPlayerMark(to, "v_armorInvalidity-turn", 1)
    end
  end,
}

--------------------------------------------------
--星汐
--------------------------------------------------

local xingxi_tianjiliuxing = General(extension,"xingxi_tianjiliuxing", "psp", 4, 4, General.Female)
xingxi_tianjiliuxing:addSkill(v_xingyao)

--------------------------------------------------
--贮歌
--需要关注后续新月杀疑似无法拦截“不能打出”的问题
--------------------------------------------------

local v_zhuge = fk.CreateViewAsSkill{
  name = "v_zhuge",
  anim_type = "offensive",
  pattern = "slash",
  card_filter = function(self, to_select, selected)
    return false
  end,
  view_as = function(self, cards)
    if #cards ~= 0 then
      return nil
    end
    local c = Fk:cloneCard("slash")
    c.skillName = self.name
    return c
  end,
  enabled_at_play = function(self, player)
    return player:usedSkillTimes(self.name, Player.HistoryTurn) == 0
  end,
  enabled_at_response = function(self, player)
    return player:usedSkillTimes(self.name, Player.HistoryTurn) == 0
  end,
}
local v_zhugeResponse = fk.CreateTriggerSkill{
  name = "#v_zhugeResponse",
  events = {fk.PreCardUse, fk.PreCardRespond},
  mute = true,
  priority = 10,
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self.name, true) and table.contains(data.card.skillNames, "v_zhuge")
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    room:doIndicate(player.id, TargetGroup:getRealTargets(data.tos))
    return true
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local judge = {
      who = player,
      reason = self.name,
      pattern = ".|.|club,spade",
    }
    room:judge(judge) 
    return judge.card.color ~= Card.Black
  end,
}
v_zhuge:addRelatedSkill(v_zhugeResponse)

--------------------------------------------------
--绝调
--------------------------------------------------

local v_juediao = fk.CreateTriggerSkill{
  name = "v_juediao",
  anim_type = "control",
  events = {fk.TargetSpecified},
  can_trigger = function(self, event, target, player, data)
    local room = player.room
    return player == target and player:hasSkill(self.name)
    and data.card
    and data.card.trueName == "slash" 
    and not table.find(player.player_cards[Player.Hand],function(id)                  --room:getCardIds(Player.Hand), function(id)
    return Fk:getCardById(id).type == Card.TypeBasic end)                        --Fk:getCardById(id).type == Card.TypeBasic end)  
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local cards = player.player_cards[Player.Hand]
    player:showCards(cards)
    data.disresponsive = true
    -- data.disresponsiveList = data.disresponsiveList or {}
    -- for _, p in ipairs (room:getAllPlayers()) do
    --   table.insertIfNeed(data.disresponsiveList, p)
    -- end    
  end,
}

--------------------------------------------------
--春野萌
--------------------------------------------------

local chunyemeng_keliyuesheng = General(extension, "chunyemeng_keliyuesheng", "novus", 4, 4, General.Female)
chunyemeng_keliyuesheng:addSkill(v_zhuge)
chunyemeng_keliyuesheng:addSkill(v_juediao)

--------------------------------------------------
--姜撞
--------------------------------------------------

local v_jiangzhuang_filter = fk.CreateFilterSkill{
  name = "#v_jiangzhuang_filter",
  card_filter = function(self, card, player, isJudgeEvent)
    return player:hasSkill(self) and card.type == Card.TypeEquip and
    (table.contains(player.player_cards[Player.Hand], card.id) or isJudgeEvent)
  end,
  view_as = function(self, card)
    return Fk:cloneCard("jink", nil, card.number)
  end,
}
local v_jiangzhuang = fk.CreateTriggerSkill{
  name = "v_jiangzhuang",
  events = {fk.BeforeCardsMove},
  frequency = Skill.Compulsory,
  anim_type = "defensive",
  can_trigger = function(self, event, target, player, data)
    if (not player:hasSkill(self)) or (not (player.phase == Player.NotActive)) then return false end
    for _, move in ipairs(data) do
      if move.from and move.from == player.id then
        for _, info in ipairs(move.moveInfo) do
          if info.fromArea == Card.PlayerEquip then
            return true
          end
        end
      elseif move.to and move.to == player.id then
        for _, info in ipairs(move.moveInfo) do
          if info.toArea == Card.PlayerEquip then
            return true
          end
        end
      end
    end
  end,
  on_use = function(self, event, target, player, data)
    local ids = {}
    --无法置入装备区装备还没做好···
    for _, move in ipairs(data) do
      if move.from and move.from == player.id then
        local move_info = {}
        for _, info in ipairs(move.moveInfo) do
          local id = info.cardId
          if info.fromArea == Card.PlayerEquip then
            table.insert(ids, id)
          else
            table.insert(move_info, info)
          end
        end
        if #ids > 0 then
          move.moveInfo = move_info
          player.room:sendLog{
            type = "#v_cancelEquip1",
            from = player.id,
            card = ids,
            arg = self.name,
          }
        end
      elseif move.to and move.to == player.id then
        local move_info = {}
        for _, info in ipairs(move.moveInfo) do
          local id = info.cardId
          if info.toArea == Card.PlayerEquip then
            table.insert(ids, id)
          else
            table.insert(move_info, info)
          end
        end
        if #ids > 0 then
          move.moveInfo = move_info
          player.room:sendLog{
            type = "#v_cancelEquip2",
            to = { player.id } ,
            card = ids,
            arg = self.name,
          }
        end
      end
    end
  end,
}

v_jiangzhuang:addRelatedSkill(v_jiangzhuang_filter)

--------------------------------------------------
--玄鳞
--------------------------------------------------

local v_xuanlin_maxcards = fk.CreateMaxCardsSkill{
  name = "#v_xuanlin_maxcards",
  exclude_from = function(self, player, card)
    if player:hasSkill(self) then
      return card.color ~= Card.Red
    end
  end,
}

local v_xuanlin = fk.CreateTriggerSkill{
  name = "v_xuanlin",
  anim_type = "defensive",
  mute = true,
  events = {fk.EventPhaseStart},
  --触发条件：
  -- ...遍历到的角色持有该技能；
  can_trigger = function(self, event, target, player, data)
    if event == fk.EventPhaseStart then
      local not_red_count = 0
      for _,cid in ipairs(player:getCardIds(Player.Hand)) do
        if Fk:getCardById(cid).color ~= Card.Red then
          not_red_count = not_red_count + 1
          if not_red_count >= 2 then
            break
          end
        end
      end
      return target == player and player:hasSkill(self) and
        player.phase == Player.Finish and
        not_red_count >= 2
    end
  end,
  --后续如果有skillnullify可以考虑在这里写
  on_cost = function(self, event, target, player, data)
    local room = player.room
    local prompt = "#v_xuanlin_invoke"
    local color = "heart,diamond"
    local dis = room:askForDiscard(player, 2, 2, false, self.name, true, ".|.|^(" .. color .. ")", prompt)
    --确认是否发动技能。
    if #dis == 2 then
      return true
    end
  end,
  --思路：
  --列出可用装备区（怎么判断装备区在不在再说···）
  --可用装备区大于0：进行选择，选择出结果
  --根据结果从牌堆和弃牌堆里找出所有的排然后随机一张给对方。（这部分可以参考小毛成长）
  on_use = function(self, event, target, player, data)
    local room = player.room
    local choices = {}
    for i = 1, 5 do
      if #player:getAvailableEquipSlots(i+2) > 0 then -- 五个装备区编号是3到7 详见 Card.SubtypeWeapon
        table.insert(choices, "v_EquipArea"..i)
      end
    end
    if #choices > 0 then
      local choice = room:askForChoice(player, choices, self.name)
      if choice and choice ~= "" then
        local i = tonumber(string.match(choice, "%d"))
        -- local slots = {Player.WeaponSlot, Player.ArmorSlot, Player.DefensiveRideSlot, Player.OffensiveRideSlot, Player.TreasureSlot}
        local slots = {Card.SubtypeWeapon, Card.SubtypeArmor, 
          Card.SubtypeDefensiveRide, Card.SubtypeOffensiveRide, Card.SubtypeTreasure}
        local slot = slots[i]
        -- room:abortPlayerArea(player, {slot})
        local allcards = {}
        table.insertTable(allcards, room.draw_pile)
        table.insertTable(allcards, room.discard_pile)
        local equips = table.filter(allcards, function(id)
          local card = Fk:getCardById(id)
          return card.type == Card.TypeEquip
            and card.sub_type == slot
            --这里后续用util的canusecard
            and VslUtil.canUseCard(room, player, card)
        end)
        if #equips > 0 then
          local x = #(equips)
          local c = math.random(1, x)
          local cid = equips[c]
          if VslUtil.canUseCard(room, player, Fk:getCardById(cid)) then
            --这种函数可以从表中随机选n个元素并返回一张表，如果n是nil，那么返回的就不是表而是单个元素
            --local card = table.random(equips, nil)
            local new_use = {} ---@type CardUseStruct
            new_use.from = player.id
            --技能马克：可能会存在类似于知更酱多目标BUG的问题
            new_use.tos = { { player.id } }
            new_use.card = Fk:getCardById(cid)
            new_use.skillName = self.name
            room:useCard(new_use)
          end
        else
          room:sendLog{
            type = "#v_xuanlin_find_fail",
            arg = self.name,
          }
        end
      end
    end

    room:doAnimate("InvokeSkill", {
      name = self.name,
      player = player.id,
      skill_type = self.anim_type,
    })
    player:broadcastSkillInvoke(self.name)
  end
}

v_xuanlin:addRelatedSkill(v_xuanlin_maxcards)

--------------------------------------------------
--礼墨
--------------------------------------------------

local limo_longshengjiangjiao = General(extension, "limo_longshengjiangjiao", "novus", 4, 4, General.Female)
limo_longshengjiangjiao:addSkill(v_jiangzhuang)
limo_longshengjiangjiao:addSkill(v_xuanlin)

--------------------------------------------------
--浅唱
--------------------------------------------------

local v_qianchang = fk.CreateViewAsSkill{
  name = "v_qianchang",
  interaction = UI.ComboBox {choices = VslUtil.not_damage_tricks},
  enabled_at_play = function(self, player)
    return player:usedSkillTimes(self.name, Player.HistoryPhase) == 0 and not player:isKongcheng()
  end,
  card_filter = function()
    return false
  end,
  view_as = function(self, cards)
    local card = Fk:cloneCard(self.interaction.data)
    card:addSubcards(Self:getCardIds(Player.Hand))
    card.skillName = self.name
    return card
  end,
}

--------------------------------------------------
--明贤
--TODO: 
--------------------------------------------------

local v_mingxian = fk.CreateTriggerSkill{
  name = "v_mingxian",
  --赋予防御型技能定义,
  anim_type = "defensive",
  --技能为锁定技，满足条件后强制发动
  frequency = Skill.Compulsory,
  --时机：目标确定后
  events = {fk.TargetSpecified},
  --触发条件：
  --         遍历到的角色具有本技能
  --         存在卡，且卡的真名为“杀”
  --         卡的颜色为红色/卡的名字为“雷杀”
  --         使用牌的角色存在、使用牌的角色存活、使用牌的角色不为遍历到的角色
  --         牌的目标存在，牌的目标中存在遍历到的角色
  --         本次流程中第一次触发这个时机
  can_trigger = function(self, event, target, player, data)
    local room = player.room
    local pla = room:getPlayerById(data.from)
    local target_contain_player = false
    for _, p in ipairs(AimGroup:getAllTargets(data.tos)) do
      if p == player.id then
        target_contain_player = true
      end
    end
    return player:hasSkill(self) 
    and data.card and data.card.trueName == "slash" 
    and (data.card.color == Card.Red or data.card.name == "thunder__slash")
    and pla and pla:isAlive() and pla ~= player
    and #AimGroup:getAllTargets(data.tos) > 0 and target_contain_player
    and data.firstTarget
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local pla = room:getPlayerById(data.from)
    --if data.from ~= player then
    --doindicate的两个参数均为integer类型，一般为角色id
    room:doIndicate( pla.id, {player.id} )
    --end
    --询问是否交对应的牌，如存在，继续，否则失效。
    local prompt = "#v_mingxian_give:"..player.id
    local slash_or_not = room:askForCard(pla, 1, 1, false, self.name, true,"slash|.|.|hand" ,prompt)[1]
    if slash_or_not then
      room:obtainCard(player, slash_or_not, true, fk.ReasonGive)
    else
      local address = "./packages/"..VslUtil.extensionName.."/image/anim/skill_nullify"
      room:setEmotion(player, address)
      table.insert(data.nullifiedTargets, player.id)
    end
  end,
}

--------------------------------------------------
--诗小雅
--角色马克：
--------------------------------------------------

local shixiaoya_xianyadan = General(extension,"shixiaoya_xianyadan", "chaociyuan", 3, 3, General.Female)
shixiaoya_xianyadan:addSkill(v_qianchang)
shixiaoya_xianyadan:addSkill(v_mingxian)

--------------------------------------------------
--抹挑
--技能马克：
-- “本回合至多造成一次伤害”后续可以补动画。
--注释：本技能将导致造成一次伤害后，伤害传导也无效。
--------------------------------------------------

local v_motiao_invalidity = fk.CreateInvaliditySkill {
  name = "#v_motiao_invalidity",
  invalidity_func = function(self, from, skill)
    if from:getMark("@@v_motiao_invalidity-turn") > 0 then
      return skill:isEquipmentSkill()
    end
  end
}
local v_motiao = fk.CreateTriggerSkill{
  name = "v_motiao",
  --赋予摸牌型技能定义
  anim_type = "drawcard",
  --时机：阶段开始时，目标指定后
  events = {fk.EventPhaseStart, fk.TargetSpecified},
  --触发条件：
  --（阶段开始时）触发时机的角色为遍历到的角色；遍历到的角色具有本技能；
  --              被遍历到的角色处于回合开始阶段。
  --（目标指定时）触发时机的角色为遍历到的角色；遍历到的角色具有本技能；
  --             存在回合开始阶段时使用此技能的标签；
  --             被指定的角色中存在遍历到的角色。
  --             本次流程中第一次触发这个时机
  can_trigger = function(self, event, target, player, data)
    if event == fk.EventPhaseStart then
      return target == player and player:hasSkill(self)
      and player.phase == Player.Start
    elseif event == fk.TargetSpecified then
      local room = player.room
      --遍历所有被指定到的角色，确认是否存在遍历到的角色
      local motiao_useornot = false
      local targets = data
      local motiao_tar = AimGroup:getAllTargets(targets.tos)
      for _, p in ipairs(motiao_tar) do
        local pls = room:getPlayerById(p)
        if pls == player then
          motiao_useornot = true
        end
      end
      return target == player and player:hasSkill(self)
      and player:getMark("v_motiao_using-turn") > 0
      and motiao_useornot
      and targets.firstTarget
    end
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    --确认是否发动技能。
    if event == fk.EventPhaseStart then
      local prompt = "v_motiao_choice"
      if room:askForSkillInvoke(player, self.name, data, prompt) then
        return true
      end
    --满足技能发动要求后，锁定发动。
    elseif event == fk.TargetSpecified and player:getMark("v_motiao_using-turn") > 0 then
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    --以on_cost中做出选择为代价，本回合内你只能造成1点伤害，你使用牌指定自己为目标之一后，摸一张牌。
    if event == fk.EventPhaseStart then
      room:setPlayerMark(player, "v_motiao_using-turn", 1)
      room:setPlayerMark(player, "@@v_motiao_using-turn", 1)
      room:setPlayerMark(player, "@@v_motiao_invalidity-turn", 1)
    --摸一张牌
    elseif event == fk.TargetSpecified then
      player:drawCards(1, self.name)
    end
  end,

  -- 伤害及抹挑装备失效在这里刷新。
  refresh_events = {fk.DamageCaused, fk.Damage},
  -- 刷新时机：
  --             触发时机的角色为遍历到的角色；遍历到的角色具有本技能；
  --             存在回合开始阶段时使用此技能的标签；
  --             造成的伤害大于0；
  --             非光属性伤害（暂未实装）。
  can_refresh = function(self, event, target, player, data)
    if not (target == player and player:hasSkill(self)) then
      return false
    end
    if event == fk.DamageCaused or event == fk.Damage then
      return player:getMark("v_motiao_using-turn") > 0
        and data.damage > 0
    -- elseif event == fk.EventPhaseChanging then
    --   return target == player and player:getMark("@@v_motiao_invalidity") > 0
    --   and data.from == Player.NotActive and data.to ~= Player.NotActive
    --   return player:getMark("v_motiao_using-turn") > 0
    end
  end,
  on_refresh = function(self, event, target, player, data)
    local room = player.room
    if event == fk.DamageCaused then
      if player:getMark("@@v_motiao_after-turn") > 0 then
        local address = "./packages/"..VslUtil.extensionName.."/image/anim/skill_nullify"
        room:setEmotion(data.to, address)
        room:sendLog{
          type = "#defense_damage",
          from = player.id,
          --log.to是数组
          to = {data.to.id},
          arg = self.name,
          arg2 = data.damage,
        }
        data.damage = 0
      end
    elseif event == fk.Damage then
      room:setPlayerMark(player, "@@v_motiao_using-turn", 0)
      room:setPlayerMark(player, "@@v_motiao_after-turn", 1)
    -- elseif event == fk.EventPhaseChanging then
    --   room:setPlayerMark(player, "@@v_motiao_invalidity", 0)
    end
  end
}
v_motiao:addRelatedSkill(v_motiao_invalidity)

--------------------------------------------------
--连奏
--技能马克：打出的牌可能会无法返回number；丈八在下版本前可能还是算点数的。
--------------------------------------------------

local v_lianzou = fk.CreateTriggerSkill{
  name = "v_lianzou",
  --赋予摸牌型技能定义
  anim_type = "drawcard",
  --时机：阶段结束时
  events = {fk.EventPhaseEnd},
  --触发条件：
  --（阶段结束时）触发时机的角色为遍历到的角色；遍历到的角色具有本技能；
  --              被遍历到的角色处于出牌阶段。
  --              被遍历到的角色本轮使用/打出牌的点数之和>=50（打出是否算入在内待定）
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self)
    and player.phase == Player.Play
    and player:getMark("@v_lianzou_count-turn") >= 50
  end,
  on_cost = function(self, event, target, player, data)
    --确认是否发动技能。
    local room = player.room
    if room:askForSkillInvoke(player,self.name,data) then
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    --判定直到点数大于等于50
    if event == fk.EventPhaseEnd then
      --这里可以后续放限定动画并给大概2500ms的延时+音效。
      local count = 0
      local dummy = Fk:cloneCard("slash")
      while count < 50 do
        local judge = {
          who = player,
          reason = self.name,
          pattern = ".|1~"..(50-count).."|.",
        }
        room:judge(judge)
        local result = judge.card
        count = count + result.number
        if count < 50 then
          dummy:addSubcard(result)
        end
      end
      room:obtainCard(player.id, dummy, true)
    end
  end,

  --刷新时机：手牌结算后，手牌打出结算后（本时机伴随希贝尔上线，与之同步因此删除）
  refresh_events = {fk.CardUseFinished},
  --刷新条件
  --（手牌结算后，手牌打出结算后（这个待定））
  --             触发时机的角色为遍历到的角色；遍历到的角色具有本技能；
  --              被遍历到的角色处于出牌阶段。
  can_refresh = function(self, event, target, player, data)
    -- if not (target == player and player:hasSkill(self)) then
    --   return false
    -- end
    return target == player and player:hasSkill(self)
    and player.phase == Player.Play
  end,
  on_refresh = function(self, event, target, player, data)
    local room = player.room
    --在满足以下条件的前提下，将牌的点数加入某个mark里。
    -- 卡牌存在，为实体牌, 卡牌点数小于等于13大于0。
    local card = data
    if card.card and card.card.id > 0 and card.card.number <= 13 and card.card.number > 0 then
      room:addPlayerMark(player, "@v_lianzou_count-turn", card.card.number)
    end
  end
}

--------------------------------------------------
--弦羽
--角色马克：抹挑
--------------------------------------------------

local xianyu_xiangluancuxian = General(extension,"xianyu_xiangluancuxian", "chaociyuan", 3, 3, General.Female)
xianyu_xiangluancuxian:addSkill(v_motiao)
xianyu_xiangluancuxian:addSkill(v_lianzou)

--------------------------------------------------
--贵胄
--------------------------------------------------

local v_guizhou = fk.CreateTriggerSkill{
  name = "v_guizhou",
  anim_type = "defensive",
  events = {fk.TargetConfirming},
  can_trigger = function(self, event, target, player, data)
    --后续可以在这里增加伤害来源是否可以对目标使用杀的判定canuse，可以参考官方的utility改良一下；
    --避免如鬼勇之类的技能的问题。
    local ret = target == player and player:hasSkill(self) and
      (data.card.trueName == "slash" or data.card.name == "duel" )
    if ret then
      self.target_list = {}
      local room = player.room
      for _, p in ipairs(room:getOtherPlayers(player)) do
        if p.id ~= data.from and p:inMyAttackRange(player) then
          table.insert(self.target_list, p.id)
        end
      end
      return #self.target_list > 0
    end
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    local prompt = "#v_guizhou_target:"..data.from.."::"..data.card.name
    local plist, cid = room:askForChooseCardAndPlayers(player, self.target_list, 1, 1, nil, prompt, self.name, true)
    if #plist > 0 then
      self.cost_data = {plist[1], cid}
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local to = self.cost_data[1]
    room:doIndicate(player.id, { to })
    if not data.card:isVirtual() then
      room:sendLog{
        type = "#v_guizhou_log",
        from = data.from,
        to = { to },
        arg = self.name,
        card = { data.card.id },
      }
    elseif data.card:isVirtual() then
      room:sendLog{
        type = "#v_guizhou_virtual_log",
        from = data.from,
        to = { to },
        arg = self.name,
        arg2 = data.card:toLogString(),
      }
    end
    room:throwCard(self.cost_data[2], self.name, player, player)
    TargetGroup:removeTarget(data.targetGroup, player.id)
    TargetGroup:pushTargets(data.targetGroup, to)
  end,
}

--------------------------------------------------
--苦情
--技能马克：
--------------------------------------------------

local v_kuqing = fk.CreateTriggerSkill{
  name = "v_kuqing",
  --赋予控场型技能定义
  anim_type = "control",
  --时机：受到伤害后
  events = {fk.Damaged},
  --触发条件：
  -- 遍历到的角色具有本技能
  -- 伤害大于0，触发时机的角色处于遍历到的角色攻击范围内
  -- 触发时机的角色区域内有牌
  can_trigger = function(self, event, target, player, data)
    local damage = data
    return player:hasSkill(self) 
    and damage.damage > 0 and player:inMyAttackRange(target)
    and (not target:isNude())
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    local prompt = "#v_kuqing_use:"..target.id
    if (not player:isKongcheng()) then
      local ret = room:askForDiscard(player, 1, 1, false, self.name, true, ".", prompt)
      --需要的话在这里增加技能检测失效
      if #ret > 0 then
        return true
      end
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local card = room:askForCardChosen(player, target, "he", self.name)
    room:obtainCard(player.id, card, false)
  end,
}

--------------------------------------------------
--诺拉
--角色马克：
--------------------------------------------------

local nuola_canglangzhixin = General(extension,"nuola_canglangzhixin", "RainbowPro", 3, 3, General.Female)
nuola_canglangzhixin:addSkill(v_guizhou)
nuola_canglangzhixin:addSkill(v_kuqing)

--------------------------------------------------
--应激
--------------------------------------------------

local v_yingji_buff = fk.CreateTargetModSkill{
  name = "#v_yingji_buff",
  residue_func = function(self, player, skill, scope, card)
    if player:getMark("@@v_yingji-turn") > 0 then
      return 999
    end
  end,
  distance_limit_func =  function(self, player, skill, card)
    if player:getMark("@@v_yingji-turn") > 0 then
      return 999
    end
  end,
}
local v_yingji = fk.CreateTriggerSkill{
  name = "v_yingji",
  --赋予卖血型技能定义
  anim_type = "masochism",
  --时机：受到伤害后
  events = {fk.Damaged},
  --触发条件：触发时机的角色为遍历到的角色、遍历到的角色具有本技能，伤害大于0，存在伤害来源，伤害来源存活。
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self) 
    and data.damage > 0 and data.from and data.from:isAlive()
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    local prompt = "v_yingji_choice:"..data.from.id
    if room:askForSkillInvoke(player, self.name, data, prompt) then
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    --执行判定，判定如为锦囊牌，则触发效果。
    local room = player.room
    if player.id ~= data.from.id then
      room:doIndicate( player.id, {data.from.id} )
    end
    --如果存在skillnullify和caneffect，可以考虑在这里放无效。
    data.from:turnOver()
    data.from:drawCards(1, self.name)
    room:setPlayerMark(data.from, "@@v_yingji-turn", 1)
  end,
}
v_yingji:addRelatedSkill(v_yingji_buff)

--------------------------------------------------
--附身
--1. 需要为extra_turn的tag处理做额外skill，以及技能发动判定也要注意
--2. 需要为技能开始和结束做两种判定逻辑···
--3. 安装和卸载装备的特效无法被无效化，可能会出现换过去的时候触发，换回来的时候不触发的场面（先村寄耦摆）
--------------------------------------------------

local v_fushen_invalidity = fk.CreateInvaliditySkill {
  name = "#v_fushen_invalidity",
  invalidity_func = function(self, from, skill)
    return (from:getMark("@@v_fushen_target") > 0
      and not skill.attached_equip)
  end
}

local v_fushen = fk.CreateTriggerSkill{
  --（刚需）技能认证名
  name = "v_fushen",
  --(非必要）赋予特殊型技能定义
  anim_type = "special",
  mute = true,
  frequency = Skill.Limited,
  --时机：阶段开始时，阶段变化时
  events = {fk.EventPhaseStart,fk.EventPhaseEnd,fk.EventPhaseChanging},
  --触发条件：
  --（通用）触发时机的角色为遍历到的角色（已完成）
  --（阶段开始时）遍历到的角色处于Notactive阶段、遍历到的角色存在invoke标记、（已完成）
  --             遍历到的角色不处于extra_turn
  --             （目前做不到，建议以后触发额外回合的时候做个额外mark陪着···）。
  --（阶段变化时）遍历到的角色存在invoking标记、遍历到的角色处于Notactive阶段。
  --（阶段变化时）遍历到的角色尚未使用过技能、遍历到的角色将进入出牌阶段、遍历到的角色存在出牌阶段。（已完成）
  can_trigger = function(self, event, target, player, data)
    if not (target == player and player:hasSkill(self)) then return false end
    if event == fk.EventPhaseStart then
      return player.phase == Player.NotActive and player:getMark("v_fushen_invoke") > 0
    elseif event == fk.EventPhaseEnd then
      return 
        player:getMark("v_fushen_invoking") > 0 
        and player.phase == Player.Finish
    elseif event == fk.EventPhaseChanging then
      return
        player:usedSkillTimes(self.name, Player.HistoryGame) == 0 
        and data.to == Player.Play and VslUtil.exist_or_not(player, Player.Play)
    end
  end,
  --使用条件：（已完成）
  --（阶段开始时）消除invoke标记，给定范围，选择玩家，如果存在，return true。
  --（阶段结束时）return true。
  --（阶段变化时）askforskillinvoke。
  on_cost = function(self, event, target, player, data)
    local room = player.room
    if event == fk.EventPhaseStart then
      room:setPlayerMark(player, "v_fushen_invoke", 0)
      local targets = {}
      for _, p in ipairs(room:getOtherPlayers(player)) do
        --后续可以在这里筛选caneffect角色。
        table.insert(targets, p.id)
      end

      if #targets > 0 then
        local to = room:askForChoosePlayers(player, targets, 1, 1, "#v_fushen_target_choose", self.name, false)[1]
        if to then
          self.cost_data = to
          return true
        end
      end
    elseif event == fk.EventPhaseEnd then
      return true
    elseif event == fk.EventPhaseChanging then
      if room:askForSkillInvoke(player, self.name, data) then
        return true
      end
    end
  end,
  --使用效果：
  --（阶段开始时）发送附身信息等；换位置；获得对方技能；获得额外回合；
  -- PS:这个阶段你要是把对面扬了，直接报错，然后这个角色没了，但你依然可以打她。
  --（阶段结束时）发送结束附身信息；换回来；
  --（阶段变化时）失去附身未使用标记；获得invoke标记；跳过出牌阶段。
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.EventPhaseStart then
      local to = room:getPlayerById(self.cost_data)
      room:setPlayerMark(player, "v_fushen_to", self.cost_data)
      room:setPlayerMark(player, "v_fushen_invoking", 1)
      local skills = {}
      room:sendLog{
        type = "#v_fushen_log",
        from = player.id,
        to = {to.id},
        arg = self.name,
      }
      --这里看情况决定要不要写指示线
      if player ~= to then
        --doindicate的两个参数均为integer类型，一般为角色id
        room:doIndicate(player.id, { to.id })
      end
      room:notifySkillInvoked(player, self.name)
      VslUtil.swap_player(player, player, to, self.name, true)
      room:setPlayerMark(player, "@@v_fushen_using", 1)
      room:setPlayerMark(to, "@@v_fushen_target", 1)
      for _, skill_name in ipairs(to.player_skills) do
        -- print(skill_name) --这步没问题
        -- print(skill_name.lordSkill)
        -- print(skill_name.frequency)
        if (
          (not skill_name.lordSkill)
          and (skill_name.frequency ~= Skill.Limited) 
          and (skill_name.frequency ~= Skill.Wake)
          and not skill_name.attached_equip
          ) 
          and not table.find(player.player_skills, 
          function(skill_name_player)
            return skill_name_player == skill_name
          end
        ) then
          -- print(skill_name)
          table.insertIfNeed(skills, skill_name.name)
        end
      end
      if #skills > 0 then
        room:setPlayerMark(player, "v_fushen_skills", skills)
        room:handleAddLoseSkills(player, table.concat(skills, "|"), nil, true, false)
      end
      player:gainAnExtraTurn()
    elseif event == fk.EventPhaseEnd then
      room:setPlayerMark(player, "v_fushen_invoking", 0)
      local to = room:getPlayerById(player:getMark("v_fushen_to"))
      room:sendLog{
        type = "#v_fushen_end_log",
        from = player.id,
        to = {to.id},
        arg = self.name,
      }
      if to:isAlive() and player:isAlive() then
        VslUtil.swap_player(player, player, to, self.name, true)
      else
        room:swapSeat(player, to)
      end
      room:setPlayerMark(player, "@@v_fushen_using", 0)
      room:setPlayerMark(to, "@@v_fushen_target", 0)
      local skills = player:getMark("v_fushen_skills")
      room:setPlayerMark(player, "v_fushen_skills", 0)
      if skills ~= 0 and #skills > 0 then
        room:handleAddLoseSkills(player, "-"..table.concat(skills, "|-"), nil, true, false)
      end
    elseif event == fk.EventPhaseChanging then
      room:setPlayerMark(player, "@@v_fushen", 0)
      room:setPlayerMark(player, "v_fushen_invoke", 1)
      return true
    end
  end,
}

v_fushen:addRelatedSkill(v_fushen_invalidity)

--------------------------------------------------
--附身测试

--需要注意死亡交换控制权
--------------------------------------------------

local v_fushen2 = fk.CreateTriggerSkill{
  --（刚需）技能认证名
  name = "v_fushen2",
  --(非必要）赋予特殊型技能定义
  anim_type = "special",
  mute = true,
  frequency = Skill.Limited,
  --时机：阶段开始时，阶段变化时
  events = {fk.EventPhaseStart,fk.EventPhaseEnd,fk.EventPhaseChanging},
  --触发条件：
  --（通用）触发时机的角色为遍历到的角色（已完成）
  --（阶段开始时）遍历到的角色处于Notactive阶段、遍历到的角色存在invoke标记、（已完成）
  --             遍历到的角色不处于extra_turn
  --             （目前做不到，建议以后触发额外回合的时候做个额外mark陪着···）。
  --（阶段变化时）遍历到的角色存在invoking标记、遍历到的角色处于Notactive阶段。
  --（阶段变化时）遍历到的角色尚未使用过技能、遍历到的角色将进入出牌阶段、遍历到的角色存在出牌阶段。（已完成）
  can_trigger = function(self, event, target, player, data)
    -- if not (target == player and player:hasSkill(self)) then return false end
    if event == fk.EventPhaseStart then
      return target == player and player:hasSkill(self)
        and player.phase == Player.NotActive and player:getMark("v_fushen_invoke") > 0
    elseif event == fk.EventPhaseEnd then
      --需要注意你这里上的是被控制的人的号。
      return target == player and
        player:getMark("v_fushen_invoked") > 0 
        and player.phase == Player.Finish
    elseif event == fk.EventPhaseChanging then
      return target == player and player:hasSkill(self)
        and player:usedSkillTimes(self.name, Player.HistoryGame) == 0 
        and data.to == Player.Play and VslUtil.exist_or_not(player, Player.Play)
    end
  end,
  --使用条件：（已完成）
  --（阶段开始时）消除invoke标记，给定范围，选择玩家，如果存在，return true。
  --（阶段结束时）return true。
  --（阶段变化时）askforskillinvoke。
  on_cost = function(self, event, target, player, data)
    local room = player.room
    if event == fk.EventPhaseStart then
      room:setPlayerMark(player, "v_fushen_invoke", 0)
      local targets = {}
      for _, p in ipairs(room:getOtherPlayers(player)) do
        --后续可以在这里筛选caneffect角色。
        table.insert(targets, p.id)
      end

      if #targets > 0 then
        local to = room:askForChoosePlayers(player, targets, 1, 1, "#v_fushen_target_choose", self.name, false)[1]
        if to then
          self.cost_data = to
          return true
        end
      end
    elseif event == fk.EventPhaseEnd then
      return true
    elseif event == fk.EventPhaseChanging then
      if room:askForSkillInvoke(player, self.name, data) then
        return true
      end
    end
  end,
  --使用效果：
  --（阶段开始时）发送附身信息等；换位置；获得对方技能；获得额外回合；
  -- PS:这个阶段你要是把对面扬了，直接报错，然后这个角色没了，但你依然可以打她。
  --（阶段结束时）发送结束附身信息；换回来；
  --（阶段变化时）失去附身未使用标记；获得invoke标记；跳过出牌阶段。
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.EventPhaseStart then
      local to = room:getPlayerById(self.cost_data)
      room:setPlayerMark(player, "v_fushen_to", self.cost_data)
      room:setPlayerMark(to, "v_fushen_by", player.id)
      room:setPlayerMark(player, "v_fushen_invoking", 1)
      room:setPlayerMark(to, "v_fushen_invoked", 1)
      room:sendLog{
        type = "#v_fushen_log",
        from = player.id,
        to = {to.id},
        arg = self.name,
      }
      --这里看情况决定要不要写指示线
      if player ~= to then
        --doindicate的两个参数均为integer类型，一般为角色id
        room:doIndicate(player.id, { to.id })
      end
      room:notifySkillInvoked(player, self.name)
      player:control(to)
      to:control(player)
      room:setPlayerMark(player, "@@v_fushen_using", 1)
      room:setPlayerMark(to, "@@v_fushen_target", 1)
    elseif event == fk.EventPhaseEnd then

      local from = room:getPlayerById(player:getMark("v_fushen_by"))
      room:setPlayerMark(from, "@@v_fushen_using", 0)
      room:setPlayerMark(from, "v_fushen_invoking", 0)
      room:setPlayerMark(player, "@@v_fushen_target", 0)
      room:setPlayerMark(player, "v_fushen_invoked", 0)
      room:sendLog{
        type = "#v_fushen_end_log",
        from = from.id,
        to = {player.id},
        arg = self.name,
      }
      from:control(from)
      player:control(player)

      -- local to = room:getPlayerById(player:getMark("v_fushen_to"))
      -- room:setPlayerMark(player, "@@v_fushen_using", 0)
      -- room:setPlayerMark(player, "v_fushen_invoking", 0)
      -- room:setPlayerMark(to, "@@v_fushen_target", 0)
      -- room:setPlayerMark(to, "v_fushen_invoked", 0)
      -- room:sendLog{
      --   type = "#v_fushen_end_log",
      --   from = player.id,
      --   to = {to.id},
      --   arg = self.name,
      -- }
      -- player:control(player)
      -- to:control(to)

    elseif event == fk.EventPhaseChanging then
      room:setPlayerMark(player, "@@v_fushen", 0)
      room:setPlayerMark(player, "v_fushen_invoke", 1)
      return true
    end
  end,
}

--------------------------------------------------
--夕兔
--------------------------------------------------

local xitu_duoshelingtu = General(extension, "xitu_duoshelingtu", "keasofer", 3, 3, General.Female)
xitu_duoshelingtu:addSkill(v_yingji)
xitu_duoshelingtu:addSkill(v_fushen)
-- xitu_duoshelingtu:addSkill(v_fushen2)

--------------------------------------------------
--幽蓝
--技能马克：缺少七海表情包
--------------------------------------------------

local v_youlan = fk.CreateTriggerSkill{
  --（刚需）技能认证名
  name = "v_youlan",
  --(非必要）赋予特殊型技能定义
  anim_type = "special",
  --技能为锁定技，满足条件后强制发动
  frequency = Skill.Compulsory,
  --时机：受到伤害时，造成伤害时
  events = {fk.DamageInflicted,fk.DamageCaused},
  --触发条件：
  --（受到伤害时）触发时机的角色为遍历到的角色、遍历到的角色具有本技能、牌为实体牌、牌的种类为锦囊牌、造成的伤害大于0。
  --（造成伤害时）造成伤害的来源为遍历到的角色、遍历到的角色具有本技能、牌为实体牌、牌的种类为锦囊牌、造成的伤害大于0。
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self) and
      (data.card and data.card.type == Card.TypeTrick)  and data.damage > 0
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.DamageInflicted then
      local address = "./packages/"..VslUtil.extensionName.."/image/skill/qihaiyouxian_2"
      room:setEmotion(player, address)
      data.damage = data.damage - 1
      if data.damage <= 0 then
        address = "./packages/"..VslUtil.extensionName.."/image/anim/skill_nullify"
        room:setEmotion(player, address)
      end
    elseif event == fk.DamageCaused then
      local address = "./packages/"..VslUtil.extensionName.."/image/skill/qihaiyouxian_1"
      room:setEmotion(player, address)
      data.damage = data.damage + 1
    end
  end,
}

--------------------------------------------------
--角色特性：箭雨（七海幽娴）
--------------------------------------------------

local v_characteristic_jianyu_qihaiyouxian = fk.CreateTriggerSkill{
  name = "#v_characteristic_jianyu_qihaiyouxian",
  anim_type = "special",
  --技能为锁定技，满足条件后强制发动
  frequency = Skill.Compulsory,
  events = {fk.GameStart},
  can_trigger = function(self, event, target, player, data)
    if not player:hasSkill(self.name, true) then
      return false
    end
    return true
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.GameStart then
      local cids = {}
      -- for i = #room.void, 1, -1 do
      --   if Fk:getCardById(room.void[i]).name == "raid_and_frontal_attack" then
      --     local idRemoved = table.remove(room.void, i)
      --     table.insert(room.draw_pile, math.random(1, #room.draw_pile), idRemoved)
      --     room:setCardArea(idRemoved, Card.DrawPile, nil)
      --   end
      -- end
      local card = room:printCard("archery_attack", Card.Heart, 7)
      table.insertIfNeed(cids, card.id)
      local ram = math.random(1, #room.draw_pile + 1)
      room:moveCards({
        ids = cids,
        toArea = Card.DrawPile,
        moveReason = fk.ReasonJustMove,
        skillName = self.name,
        drawPilePosition = ram,
      })
      room:sendLog{
				type = "#v_newcardintopile_log",
				from = player.id,
				card = cids,
				arg = self.name,
			} 
      room:doBroadcastNotify("UpdateDrawPile", #room.draw_pile)
    end
  end,
}

--------------------------------------------------
--七海幽娴
--角色马克：幽蓝，特性·箭雨未实装
--------------------------------------------------

local qihaiyouxian_zhuangzhilingyun = General(extension, "qihaiyouxian_zhuangzhilingyun", "VirtualDove", 4, 3, General.Agender)
qihaiyouxian_zhuangzhilingyun:addSkill(v_youlan)
qihaiyouxian_zhuangzhilingyun:addSkill(v_characteristic_jianyu_qihaiyouxian)

--------------------------------------------------
--险至
--------------------------------------------------

local v_xianzhi_prohibit = fk.CreateProhibitSkill{
  name = "#v_xianzhi_prohibit",
  prohibit_use = function(self, player, card)
    if player:getMark("@@v_xianzhi-turn") ~= 0 and card then
      return card.type == Card.TypeBasic
    end   
  end,
  prohibit_response = function(self, player, card)
    if player:getMark("@@v_xianzhi-turn") ~= 0 and card then
      return card.type == Card.TypeBasic
    end 
  end,
}
local v_xianzhi = fk.CreateTriggerSkill{
  name = "v_xianzhi",
  anim_type = "control",
  events ={fk.TargetSpecified,fk.CardUseFinished},
  can_trigger = function(self, event, target, player, data)
    -- if not (player == target and player:hasSkill(self)) then
    --   return false
    -- end
    local room = player.room
    if event == fk.TargetSpecified then
      if player == target and player:hasSkill(self)
        and data.card
        and (data.card.trueName == "slash" or data.card.name == "duel")
        and #AimGroup:getAllTargets(data.tos) == 1
      then
        local to = room:getPlayerById(data.to)
        local datatos = 
          -- (not to:isNude()) or 
          (not (to:getMark("@@v_xianzhi-turn") > 0))
        return datatos
      end
    elseif event == fk.CardUseFinished then
      return 
        data.card
        and data.card:getMark("v_xianzhi-turn") == player.id
    end
  end,
  on_cost = function(self, event, target, player, data)
    if event == fk.CardUseFinished then
      return true
    else
      return player.room:askForSkillInvoke(player,self.name)
    end 
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.TargetSpecified then  
      local to = room:getPlayerById(data.to)  
      --这里看情况决定要不要写指示线
      if player ~= to then
        --doindicate的两个参数均为integer类型，一般为角色id
        room:doIndicate(player.id, { to.id })
      end 
      local choiceList = {}
      if not (to:getMark("@@v_xianzhi-turn") > 0) then
        table.insert(choiceList, "#v_xianzhi1") 
      end
      -- if not to:isNude() then
		  table.insert(choiceList, "#v_xianzhi2")
      -- end
      if choiceList ~= {} then
        local choice = room:askForChoice(to, choiceList, self.name)
        if choice == "#v_xianzhi1" then
          room:sendLog{
            type = "#v_choose",
            from = to.id,
            arg = "#v_xianzhi1",
            -- arg2 = data.damage,
          }
          room:setPlayerMark(to,"@@v_xianzhi-turn", 1)
        elseif choice == "#v_xianzhi2" then
          room:sendLog{
            type = "#v_choose",
            from = to.id,
            arg = "#v_xianzhi2",
            -- arg2 = data.damage,
          }
          room:setCardMark(data.card, "v_xianzhi-turn", to.id)
        end
      end
    elseif event == fk.CardUseFinished then
      room:setCardMark(data.card, "v_xianzhi-turn", 0)
      if (not player:isNude()) then
        room:askForDiscard(player, 1, 1, true, self.name, false,".", "v_discard_1")
      else
        room:sendLog{
          type = "#v_player_discard_fail",
          from = player.id,
          arg = self.name,
        }
      end
    end
  end,
}

v_xianzhi:addRelatedSkill(v_xianzhi_prohibit)

--------------------------------------------------
--冥邀
--------------------------------------------------

local v_mingyao_distance = fk.CreateDistanceSkill{
	name = "#v_mingyao_distance",
	correct_func = function(self, from, to) return 0 end,
	fixed_func = function(self, from, to)
		if to:getMark("@@v_mingyao-round") ~= 0 then
		  return 1
		end
	end,
}

local v_mingyao = fk.CreateTriggerSkill{
  name = "v_mingyao",
  anim_type = "control",
  events = {fk.RoundStart},
  frequency = Skill.Limited,
  can_trigger = function(self, event, target, player, data)
    return player:hasSkill(self) and player:usedSkillTimes(self.name, Player.HistoryGame) == 0
  end,

  on_cost = function(self, event, target, player, data)
    local room = player.room
    local fir_targets = table.map(room:getOtherPlayers(player), function(p) return p.id end)
    local targets = {}
    --这里后续可以加caneffect
    for _, pid in ipairs(fir_targets) do
      if VslUtil.SkillCanTarget(room:getPlayerById(pid), player, self.name) then
        table.insert(targets, pid)
      end
    end
    if #targets == 0 then return end
    local to = room:askForChoosePlayers(player, targets, 1, 1, "#v_mingyao-choose", self.name, true)
    if #to > 0 then
      self.cost_data = to[1]
      return true
    end   
  end,

  on_use = function(self, event, target, player, data)
    local room = player.room
    local to = room:getPlayerById(self.cost_data)
    room:setPlayerMark(to, "@@v_mingyao-round", 1)
  end,

  refresh_events = {fk.AfterDying},
  can_refresh = function(self, event, target, player, data)
    return event == fk.AfterDying and target == player and player:getMark("@@v_mingyao-round") ~= 0 
  end,
  on_refresh = function(self, event, target, player, data)
    player.room:changeMaxHp(player, -1)
  end,
}

v_mingyao:addRelatedSkill(v_mingyao_distance)
  
--------------------------------------------------
--尼莫
--------------------------------------------------

local nimo_avatarofevil = General(extension, "nimo_avatarofevil", "individual", 4, 4, General.Female)
nimo_avatarofevil:addSkill(v_xianzhi)
nimo_avatarofevil:addSkill(v_mingyao)

--------------------------------------------------
--阳能
--------------------------------------------------

local v_yangneng = fk.CreateTriggerSkill{
  name = "v_yangneng",
  anim_type = "drawcard",
  frequency = Skill.Compulsory,
  mute = true,
  events = {fk.BeforeCardsMove, fk.AfterCardsMove, fk.EventPhaseStart},
  --使用条件：（已完成）
  -- ...
  can_trigger = function(self, event, target, player, data)
    local room = player.room
    if event == fk.BeforeCardsMove then
      if room:getTag("FirstRound") then return false end
      for _, move in ipairs(data) do
        if move.toArea == Player.Hand
          and move.to
          and move.to == player.id
          and player
          and player.phase ~= Player.NotActive
          -- and #move.ids > 0 
        then
          return true
        end
      end
    elseif event == fk.AfterCardsMove then
      if room:getTag("FirstRound") then return false end
      for _, move in ipairs(data) do
        if move.skillName ~= self.name 
          and move.toArea == Player.Hand
          and move.to
          and move.to == player.id
          and (player and player:hasSkill(self))
          and player.phase == Player.NotActive
          -- and #move.ids > 0 
        then
          return true
        end
      end
    elseif event == fk.EventPhaseStart then
      return player == target and player:hasSkill(self)
        and player.phase == Player.Discard
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.BeforeCardsMove then
      for _, move in ipairs(data) do
        for _, info in ipairs(move.moveInfo) do
          local yangneng_card = Fk:getCardById(info.cardId)
          room:setPlayerMark(player,"v_yangneng_card_"..info.cardId.."-turn", 1)
          if player:hasSkill(self) then
            room:setCardMark(yangneng_card, "@@v_yangneng-cm!dc*", 1)
          end
        end
      end
    elseif event == fk.AfterCardsMove then
      room:delay(250)
      room:notifySkillInvoked(player, self.name)
      player:broadcastSkillInvoke(self.name)
      player:drawCards(1, self.name)
    elseif event == fk.EventPhaseStart then
      local return_ids = {}
      for _,cid in ipairs(player:getCardIds(Player.Hand)) do
        if player:getMark("v_yangneng_card_"..cid.."-turn") > 0 then
          room:setPlayerMark(player, "v_yangneng_card_"..cid.."-turn", 0)
          room:setCardMark(Fk:getCardById(cid), "@@v_yangneng-cm!dc*", 0)
          table.insertIfNeed(return_ids, cid)
        end
      end
      if #return_ids > 0 then
        room:notifySkillInvoked(player, self.name)
        player:broadcastSkillInvoke(self.name)
        VslUtil.return_draw_pile(player, return_ids, self.name)
        room:delay(300)
      end
    end
  end,
}

--------------------------------------------------
--阴憩
--------------------------------------------------

local v_yinqi = fk.CreateTriggerSkill{
  name = "v_yinqi",
  anim_type = "defensive",
  frequency = Skill.Compulsory,
  events = {fk.DamageInflicted, fk.EventPhaseChanging},
  --使用条件：（已完成）
  -- ...
  can_trigger = function(self, event, target, player, data)
    if event == fk.DamageInflicted then
      return data.damage > 0 
      --  and data.from and data.to
       and player:isKongcheng()
       and player:hasSkill(self) and target == player
    elseif event == fk.EventPhaseChanging then
      return player == target and player:getMark("@v_yinqi") > 0
        and VslUtil.exist_or_not(player, Player.Draw) 
        and data.to == Player.Draw
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.DamageInflicted then
      player:drawCards(1, self.name)
      room:addPlayerMark(player, "@v_yinqi", 1)
      local address = "./packages/"..VslUtil.extensionName.."/image/anim/skill_nullify"
      room:setEmotion(player, address)
      return true
    elseif event == fk.EventPhaseChanging then
      room:removePlayerMark(player, "@v_yinqi", 1)
      player:skip(Player.Draw)
      return true
    end
  end,
}

--------------------------------------------------
--早凉
--------------------------------------------------

local zaoliang_jiqimao = General(extension, "zaoliang_jiqimao", "individual", 3, 3, General.Agender)
zaoliang_jiqimao:addSkill(v_yangneng)
zaoliang_jiqimao:addSkill(v_yinqi)

--------------------------------------------------
--撷芳
--------------------------------------------------

local v_xiefang = fk.CreateDistanceSkill{
  name = "v_xiefang",
  correct_func = function(self, from, to)
    if from:hasSkill(self) then
      local n = 0
      for _, p in ipairs(Fk:currentRoom().alive_players) do
        if p.gender == General.Female then
          n = n + 1
        end
      end
      return -n
    end
    return 0
  end,
}

--------------------------------------------------
--心动
--------------------------------------------------

local v_xindong = fk.CreateTriggerSkill{
  name = "v_xindong",
  anim_type = "drawcard",
  events = {fk.EventPhaseEnd},
  can_trigger = function(self, event, target, player, data)
    return player:hasSkill(self) and player:usedSkillTimes(self.name, Player.HistoryTurn) == 0
    and player.phase == Player.Play
  end,

  on_cost = function(self, event, target, player, data)
    local room = player.room
    local fir_targets = table.map(room:getOtherPlayers(player), function(p) return p.id end)
    local targets = {}
    --这里后续可以加caneffect
    for _, pid in ipairs(fir_targets) do
      if VslUtil.SkillCanTarget(room:getPlayerById(pid), player, self.name) and player:inMyAttackRange(room:getPlayerById(pid)) then
        table.insert(targets, pid)
      end
    end
    if #targets == 0 then return end
    local to = room:askForChoosePlayers(player, targets, 1, 3, "#v_xindong-choose", self.name, true)
    if #to > 0 then
      self.cost_data = to
      return true
    end   
  end,

  on_use = function(self, event, target, player, data)
    local room = player.room
    local tos = self.cost_data
    local to
    for _,pid in ipairs(tos) do
      to = room:getPlayerById(pid)
      room:drawCards(to, 1, self.name)
    end
    local maxcard = room:getPlayerById(tos[1]):getHandcardNum()
    local maxone = room:getPlayerById(tos[1])
    for _,pid in ipairs(tos) do
      if room:getPlayerById(pid):getHandcardNum() > maxcard then
        maxcard = room:getPlayerById(pid):getHandcardNum()
        maxone = room:getPlayerById(pid)
      end
    end
    local maxtime = 0
    for _,pid in ipairs(tos) do
      to = room:getPlayerById(pid)
      if to:getHandcardNum() == maxcard then
        maxtime = maxtime + 1
        maxone = to
      end
    end
    if maxtime == 1 then
      if maxone:getMark("@@v_xindong") == 0 then
        room:setPlayerMark(maxone, "@@v_xindong", 1)
        room:damage{
          to = maxone,
          damage = 1,
          damageType = fk.FireDamage,
          skillName = self.name,
        }
      end
    end
  end,
}

  
--------------------------------------------------
--雪狐桑
--------------------------------------------------

local xuehusang_zizaisuixin = General(extension, "xuehusang_zizaisuixin", "individual", 3, 3, General.Female)
xuehusang_zizaisuixin:addSkill(v_xiefang)
xuehusang_zizaisuixin:addSkill(v_xindong)

--------------------------------------------------
--琉彩
--------------------------------------------------

local v_liucai = fk.CreateTriggerSkill{
  name = "v_liucai",
  anim_type = "drawcard",
  frequency = Skill.Compulsory,
  events = {fk.DrawNCards},
  can_trigger = function(self, event, target, player, data)
    if target == player and player:hasSkill(self) then
      if event == fk.DrawNCards then
        return true
      end
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.DrawNCards then
      local all_suit = {"spade", "heart", "club", "diamond"}
      local dummy = Fk:cloneCard('slash', Card.NoSuit, 0)
      -- local draw_c = {}
      for _,cid in ipairs(player:getCardIds(Player.Hand)) do
        if table.contains(all_suit, Fk:getCardById(cid):getSuitString()) then
          table.removeOne(all_suit, Fk:getCardById(cid):getSuitString())
        end
      end
      if #all_suit > 0 then
        local heart_cards = {}
				local diamond_cards = {}
				local spade_cards = {}
				local club_cards = {}
        for _,cid in ipairs(room.draw_pile) do
          local c = Fk:getCardById(cid)
            if table.contains(all_suit, c:getSuitString()) then
              if c.suit == Card.Spade then
                table.insert(spade_cards, c)
              elseif c.suit == Card.Club then
                table.insert(club_cards, c)
              elseif c.suit == Card.Heart then
                table.insert(heart_cards, c)
              elseif c.suit == Card.Diamond then
                table.insert(diamond_cards, c)
              end
            end
        end
        if #heart_cards > 0 then
          dummy:addSubcard(heart_cards[math.random(1, #heart_cards)])
        end
        if #diamond_cards > 0 then
          dummy:addSubcard(diamond_cards[math.random(1, #diamond_cards)])
        end
        if #spade_cards > 0 then
          dummy:addSubcard(spade_cards[math.random(1, #spade_cards)])
        end
        if #club_cards > 0 then
          dummy:addSubcard(club_cards[math.random(1, #club_cards)])
        end
        table.shuffle(dummy.subcards)
        if #dummy.subcards > 0 then
          --这段如果后续改为不公开，log就不要展示了直接删掉。
          room:sendLog{
            type = "#v_liucai_log",
            from = player.id,
            arg = self.name,
            card = dummy.subcards,
          }
          room:obtainCard(player, dummy, true)
        end
      end
      data.n = 0
    end
  end,
}

--------------------------------------------------
--守惑
--------------------------------------------------

Fk:addPoxiMethod{
  name = "v_shouhuo_discard",
  card_filter = function(to_select, selected, data, extra_data)
    local cards1 = extra_data[1]
    local cards2 = extra_data[1]
    local hand = table.contains(cards1, to_select)
    local equip = table.contains(cards2, to_select)
    local area = true
    for i = 1,#selected do
      if hand then
        if table.contains(cards1, selected[i]) then
          area = false
        end
      elseif equip then
        if table.contains(cards2, selected[i]) then
          area = false
        end
      end
    end
    return area and not Self:prohibitDiscard(Fk:getCardById(to_select))
  end,
  feasible = function(selected, data)
    --这东西相当于 选了几个区域的牌弃置几张，没办法做到两个区域的话必须弃置两张
    if #selected < 1 or #selected > 2 then return false end
    local areas = {}
    for _, v in ipairs(data) do
      if #v[2] > 0 then
        table.insertIfNeed(areas, v[2])
      end
    end
    return #areas == #selected
  end,
  prompt = function ()
    return "守惑：弃置手牌区及装备区的牌各一张。"
  end
}

local v_shouhuo = fk.CreateTriggerSkill{
  name = "v_shouhuo",
  anim_type = "drawcard",
  events = {fk.EventPhaseStart, fk.EventPhaseChanging},
  --使用条件：（已完成）
  -- ...
  can_trigger = function(self, event, target, player, data)
    if event == fk.EventPhaseStart then
      return player:hasSkill(self) and target == player
        and player.phase == Player.Finish
        and player:getMark("@@v_shouhuo-turn") > 0
        and not player:isAllNude()
    elseif event == fk.EventPhaseChanging then
      return player == target and player:hasSkill(self)
        and VslUtil.exist_or_not(player, Player.Discard) 
        and data.to == Player.Discard
        and not player:isAllNude()
    end
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    if event == fk.EventPhaseStart then
      return true
    elseif event == fk.EventPhaseChanging then
      local prompt = "#v_shouhuo_choice"
      if room:askForSkillInvoke(player, self.name, data, prompt) then
        return true
      end
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.EventPhaseStart then
      room:setPlayerMark(player, "@@v_shouhuo-turn", 0)
      local cards1 = player:getCardIds("h")
      local cards2 = player:getCardIds("e")
      local cards = room:askForPoxi(player, "v_shouhuo_discard", {
        { VslUtil.area_type["hand"], cards1 },
        { VslUtil.area_type["equip"], cards2 },
      }, {cards1, cards2}, false)
      local moveInfos = {}
      if #cards > 0 then
        table.insert(moveInfos, {
          from = player.id,
          ids = cards,
          toArea = Card.DiscardPile,
          moveReason = fk.ReasonDiscard,
          proposer = player.id,
          skillName = self.name,
        })
      end
      room:moveCards(table.unpack(moveInfos))
    elseif event == fk.EventPhaseChanging then
      room:setPlayerMark(player, "@@v_shouhuo-turn", 1)
      player:skip(Player.Discard)
      return true
    end
  end,
}

--------------------------------------------------
--星月璃り
--------------------------------------------------

local xingyueli_gulvguixing = General(extension, "xingyueli_gulvguixing", "individual", 4, 4, General.Female)
xingyueli_gulvguixing:addSkill(v_liucai)
xingyueli_gulvguixing:addSkill(v_shouhuo)

--------------------------------------------------
--翩翩
--转换技：0为阳（白），1为阴（黑）
--------------------------------------------------

local v_pianpian = fk.CreateTriggerSkill{
  name = "v_pianpian",
  switch_skill_name = "v_pianpian",
  anim_type = "switch",
  events = {fk.EventPhaseStart},
  can_trigger = function(self, event, target, player, data)
    if not (target == player and player:hasSkill(self) and
      player:usedSkillTimes(self.name, Player.HistoryTurn) == 0 and
      player:getHandcardNum() < player:getGeneralMaxHp()) then return end

    local isYang = player:getSwitchSkillState(self.name) == fk.SwitchYang
    if player.phase == Player.Finish and isYang then
      return true
    elseif player.phase == Player.Start and not isYang then
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local isYang = player:getSwitchSkillState(self.name) == fk.SwitchYang
    player:drawCards(1, self.name)
    room:setPlayerMark(player, "@@v_pianpian-turn", 1)
    if isYang then
      room:setPlayerMark(player, "@v_pianpian_state", "O")
    elseif not isYang then
      room:setPlayerMark(player, "@v_pianpian_state", 1)
    end
  end,
}

--------------------------------------------------
--寄月
--------------------------------------------------

local v_jiyue = fk.CreateActiveSkill{
  name = "v_jiyue",
  anim_type = "special",
  min_target_num = function(self)
    if self.interaction.data == "v_jiyue_4" then
      return 1
    elseif self.interaction.data == "v_jiyue_23" then
      return 0
    end
  end,
  max_target_num = 1,
  min_card_num = function(self)
    if self.interaction.data == "v_jiyue_4" then
      return 4
    elseif self.interaction.data == "v_jiyue_23" then
      return 2
    end
  end,
  max_card_num = function(self)
    if self.interaction.data == "v_jiyue_4" then
      return 4
    elseif self.interaction.data == "v_jiyue_23" then
      return 3
    end
  end,
  interaction = function(self)
    local v_jiyue_choice = {"v_jiyue_23"}
    if Self:getHandcardNum() + #Self:getCardIds(Player.Equip) >= 4 then
      table.insert(v_jiyue_choice, "v_jiyue_4")
    end
    return UI.ComboBox {
      choices = v_jiyue_choice
    } 
  end,
  can_use = function(self, player)
    return 
      player:usedSkillTimes(self.name, Player.HistoryPhase) == 0 and 
      not player:isNude()
  end,
  card_filter = function(self, to_select, selected, targets)
    if self.interaction.data == "v_jiyue_4" then
      return #selected == 0 or 
      (#selected > 0 and #selected < 4 and Fk:getCardById(to_select).trueName == Fk:getCardById(selected[1]).trueName)
    elseif self.interaction.data == "v_jiyue_23" then
      return #selected == 0 or 
      (#selected > 0 and #selected < 3 and Fk:getCardById(to_select).trueName == Fk:getCardById(selected[1]).trueName)
    end

  end,
  target_filter = function(self, to_select, selected)
    if self.interaction.data == "v_jiyue_4" then
      --这里后续可以加caneffect
      return #selected == 0
    elseif self.interaction.data == "v_jiyue_23" then
      return false
    end
  end,
  on_use = function(self, room, effect)
    local player = room:getPlayerById(effect.from)
    local target
    if #effect.tos > 0 then
      target = room:getPlayerById(effect.tos[1])
    end
    if #effect.cards > 0 then
      VslUtil.return_draw_pile(player, effect.cards, self.name)
    end
    if #effect.cards < 4 then
      local allCardIds = Fk:getAllCardIds()
      local allCardMapper = {}
      local allCardNames = {}
      local cardType
      if #effect.cards == 2 then
        cardType = Card.TypeBasic
      elseif #effect.cards == 3 then
        cardType = Card.TypeTrick
      end
      --这段写法感觉可以考虑再优化下···
      --例如用getallcardnames获取加入游戏的卡的牌名，等到选择好了再去找对应的牌···
      for _, id in ipairs(allCardIds) do
        local card = Fk:getCardById(id)
        if card.type == cardType then
          if allCardMapper[card.name] == nil then
            table.insert(allCardNames, card.name)
          end
          allCardMapper[card.name] = allCardMapper[card.name] or {}
          if table.contains(room.draw_pile, id) then
            table.insert(allCardMapper[card.name], id)
          end
        end
      end

      if #allCardNames == 0 then
        return
      end

      local cardName = room:askForChoice(player, allCardNames, self.name)
      local toGain
      if #allCardMapper[cardName] > 0 then
        toGain = allCardMapper[cardName][math.random(1, #allCardMapper[cardName])]
        room:obtainCard(effect.from, toGain, true, fk.ReasonPrey)
      end

    elseif #effect.cards == 4 then
      player:turnOver()
      room:damage({
        from = player,
        to = target,
        damage = 3,
        damageType = fk.FireDamage,
        skillName = self.name,
      })
    end
  end,
}

--------------------------------------------------
--扇宝
--------------------------------------------------

local shanbao_fengyaliangyou = General(extension, "shanbao_fengyaliangyou", "individual", 3, 3, General.Female)
shanbao_fengyaliangyou:addSkill(v_pianpian)
shanbao_fengyaliangyou:addSkill(v_jiyue)

-- 加载本包的翻译包(load translations of this package)，这一步在本文档的最后进行。
-- dofile "packages/vupslash/i18n/init.lua"
dofile "packages/VslTest/i18n/init.lua"
  
-- return { extension } 

return extension